﻿namespace SandScript.Models
{
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Xml.Serialization;
    using SandScript.Models.Documentation;

    public enum MemberType
    {
        Primitive,
        Object,
        Property,
        Function,
        Global
    }

    public enum ClassType
    {
        None,
        Namespace,
        Constructor,
        Module
    }

    public class MemberDetail
    {
        private static readonly XmlSerializer Serializer = new XmlSerializer(typeof(Root));

        public MemberType Type { get; set; }

        public string Name { get; set; }

        public bool Readable { get; set; }

        public bool Writable { get; set; }

        public object Value { get; set; }

        public string ValueType { get; set; }

        public string Documentation { get; set; }

        public string[] Parameters { get; set; }

        public int ParameterLength { get; set; }

        public IList<MemberDetail> Members { get; set; }

        public IList<MemberDetail> Prototype { get; set; }

        public ClassType ClassType
        {
            get
            {
                if (this.Type == MemberType.Function && (this.Prototype.Count > 0 || char.IsUpper(this.Name[0])))
                {
                    return ClassType.Constructor;
                }

                if (this.Type == MemberType.Object && !this.Members.Any(x => x.Type != MemberType.Object))
                {
                    return ClassType.Namespace;
                }

                if (this.Type == MemberType.Object && this.Members.Any(x => x.Type == MemberType.Function))
                {
                    return ClassType.Module;
                }

                return ClassType.None;
            }
        }

        public Root GetDocumentation()
        {
            if (!string.IsNullOrWhiteSpace(this.Documentation))
            {
                var reader = new StringReader("<root>" + this.Documentation + "</root>");

                try
                {
                    return (Root)Serializer.Deserialize(reader);
                }
                catch
                {
                }
            }

            return null;
        }

        public bool TryGetDocumentation(out Root documentation)
        {
            documentation = this.GetDocumentation();

            return documentation != null;
        }

        public bool TryGetSignature(out Signature signature)
        {
            Root root;

            if (this.TryGetDocumentation(out root))
            {
                if (root.Signatures != null && root.Signatures.Count > 0)
                {
                    signature = root.Signatures[0];
                    return true;
                }

                signature = root;
                return true;
            }

            signature = null;
            return false;
        }
    }
}
